home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 8 / The Arsenal Files Collection #8 (Arsenal Computer) (1996).ISO / g_quake / stckybmb.zip / WEAPONS.QC < prev   
Text File  |  1996-10-17  |  29KB  |  1,361 lines

  1. /*  This sticky pipe bomb mod was made by me, it is a derivitive work
  2.         based on examples from the guys who made the following:
  3.                 Grappling Hook (Morning Star)
  4.                 Proximity Mines
  5.                 3 Way Grenade
  6.         Pressing 6 toggles between Grenade Launcher and Sticky Pipe Bomb Launcher.  Impulse 31
  7.         detonates it (them).  Feel free to modify it or distribute it.  But please put my damn
  8.         name on it.  This will probably be greatest achievment in life.  Call me
  9.         Ryan VanMiddlesworth (I am 'Scumbag V' in Quake, teammate and superior to 'Asswipe V').
  10. */
  11. float temp1=1;
  12.  
  13. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  14. void () player_run;
  15. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  16. void(vector org, vector vel, float damage) SpawnBlood;
  17. void() SuperDamageSound;
  18.  
  19. // called by worldspawn
  20. void() W_Precache =
  21. {
  22.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  23.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  24.     precache_sound ("weapons/sgun1.wav");
  25.     precache_sound ("weapons/guncock.wav");    // player shotgun
  26.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  27.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  28.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  29.     precache_sound ("weapons/spike2.wav");    // super spikes
  30.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  31.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  32.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  33.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  34.  
  35.     precache_model ("progs/v_spike.mdl"); // Sticky pipe bomb
  36. };
  37.  
  38. float() crandom =
  39. {
  40.     return 2*(random() - 0.5);
  41. };
  42.  
  43. /*
  44. ================
  45. W_FireAxe
  46. ================
  47. */
  48. void() W_FireAxe =
  49. {
  50.     local    vector    source;
  51.     local    vector    org;
  52.  
  53.     source = self.origin + '0 0 16';
  54.     traceline (source, source + v_forward*64, FALSE, self);
  55.     if (trace_fraction == 1.0)
  56.         return;
  57.     
  58.     org = trace_endpos - v_forward*4;
  59.  
  60.     if (trace_ent.takedamage)
  61.     {
  62.         trace_ent.axhitme = 1;
  63.         SpawnBlood (org, '0 0 0', 20);
  64.         T_Damage (trace_ent, self, self, 20);
  65.     }
  66.     else
  67.     {    // hit wall
  68.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  69.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  70.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  71.         WriteCoord (MSG_BROADCAST, org_x);
  72.         WriteCoord (MSG_BROADCAST, org_y);
  73.         WriteCoord (MSG_BROADCAST, org_z);
  74.     }
  75. };
  76.  
  77.  
  78. //============================================================================
  79.  
  80.  
  81. vector() wall_velocity =
  82. {
  83.     local vector    vel;
  84.     
  85.     vel = normalize (self.velocity);
  86.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  87.     vel = vel + 2*trace_plane_normal;
  88.     vel = vel * 200;
  89.     
  90.     return vel;
  91. };
  92.  
  93.  
  94. /*
  95. ================
  96. SpawnMeatSpray
  97. ================
  98. */
  99. void(vector org, vector vel) SpawnMeatSpray =
  100. {
  101.     local    entity missile, mpuff;
  102.     local    vector    org;
  103.  
  104.     missile = spawn ();
  105.     missile.owner = self;
  106.     missile.movetype = MOVETYPE_BOUNCE;
  107.     missile.solid = SOLID_NOT;
  108.  
  109.     makevectors (self.angles);
  110.  
  111.     missile.velocity = vel;
  112.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  113.  
  114.     missile.avelocity = '3000 1000 2000';
  115.     
  116. // set missile duration
  117.     missile.nextthink = time + 1;
  118.     missile.think = SUB_Remove;
  119.  
  120.     setmodel (missile, "progs/zom_gib.mdl");
  121.     setsize (missile, '0 0 0', '0 0 0');        
  122.     setorigin (missile, org);
  123. };
  124.  
  125. /*
  126. ================
  127. SpawnBlood
  128. ================
  129. */
  130. void(vector org, vector vel, float damage) SpawnBlood =
  131. {
  132.     particle (org, vel*0.1, 73, damage*2);
  133. };
  134.  
  135. /*
  136. ================
  137. spawn_touchblood
  138. ================
  139. */
  140. void(float damage) spawn_touchblood =
  141. {
  142.     local vector    vel;
  143.  
  144.     vel = wall_velocity () * 0.2;
  145.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  146. };
  147.  
  148.  
  149. /*
  150. ================
  151. SpawnChunk
  152. ================
  153. */
  154. void(vector org, vector vel) SpawnChunk =
  155. {
  156.     particle (org, vel*0.02, 0, 10);
  157. };
  158.  
  159. /*
  160. ==============================================================================
  161.  
  162. MULTI-DAMAGE
  163.  
  164. Collects multiple small damages into a single damage
  165.  
  166. ==============================================================================
  167. */
  168.  
  169. entity    multi_ent;
  170. float    multi_damage;
  171.  
  172. void() ClearMultiDamage =
  173. {
  174.     multi_ent = world;
  175.     multi_damage = 0;
  176. };
  177.  
  178. void() ApplyMultiDamage =
  179. {
  180.     if (!multi_ent)
  181.         return;
  182.     T_Damage (multi_ent, self, self, multi_damage);
  183. };
  184.  
  185. void(entity hit, float damage) AddMultiDamage =
  186. {
  187.     if (!hit)
  188.         return;
  189.     
  190.     if (hit != multi_ent)
  191.     {
  192.         ApplyMultiDamage ();
  193.         multi_damage = damage;
  194.         multi_ent = hit;
  195.     }
  196.     else
  197.         multi_damage = multi_damage + damage;
  198. };
  199.  
  200. /*
  201. ==============================================================================
  202.  
  203. BULLETS
  204.  
  205. ==============================================================================
  206. */
  207.  
  208. /*
  209. ================
  210. TraceAttack
  211. ================
  212. */
  213. void(float damage, vector dir) TraceAttack =
  214. {
  215.     local    vector    vel, org;
  216.     
  217.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  218.     vel = vel + 2*trace_plane_normal;
  219.     vel = vel * 200;
  220.  
  221.     org = trace_endpos - dir*4;
  222.  
  223.     if (trace_ent.takedamage)
  224.     {
  225.         SpawnBlood (org, vel*0.2, damage);
  226.         AddMultiDamage (trace_ent, damage);
  227.     }
  228.     else
  229.     {
  230.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  231.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  232.         WriteCoord (MSG_BROADCAST, org_x);
  233.         WriteCoord (MSG_BROADCAST, org_y);
  234.         WriteCoord (MSG_BROADCAST, org_z);
  235.     }
  236. };
  237.  
  238. /*
  239. ================
  240. FireBullets
  241.  
  242. Used by shotgun, super shotgun, and enemy soldier firing
  243. Go to the trouble of combining multiple pellets into a single damage call.
  244. ================
  245. */
  246. void(float shotcount, vector dir, vector spread) FireBullets =
  247. {
  248.     local    vector direction;
  249.     local    vector    src;
  250.     
  251.     makevectors(self.v_angle);
  252.  
  253.     src = self.origin + v_forward*10;
  254.     src_z = self.absmin_z + self.size_z * 0.7;
  255.  
  256.     ClearMultiDamage ();
  257.     while (shotcount > 0)
  258.     {
  259.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  260.  
  261.         traceline (src, src + direction*2048, FALSE, self);
  262.         if (trace_fraction != 1.0)
  263.             TraceAttack (4, direction);
  264.  
  265.         shotcount = shotcount - 1;
  266.     }
  267.     ApplyMultiDamage ();
  268. };
  269.  
  270. /*
  271. ================
  272. W_FireShotgun
  273. ================
  274. */
  275. void() W_FireShotgun =
  276. {
  277.     local vector dir;
  278.  
  279.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  280.  
  281.     self.punchangle_x = -2;
  282.     
  283.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  284.     dir = aim (self, 100000);
  285.     FireBullets (6, dir, '0.04 0.04 0');
  286. };
  287.  
  288.  
  289. /*
  290. ================
  291. W_FireSuperShotgun
  292. ================
  293. */
  294. void() W_FireSuperShotgun =
  295. {
  296.     local vector dir;
  297.  
  298.     if (self.currentammo == 1)
  299.     {
  300.         W_FireShotgun ();
  301.         return;
  302.     }
  303.         
  304.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  305.  
  306.     self.punchangle_x = -4;
  307.     
  308.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  309.     dir = aim (self, 100000);
  310.     FireBullets (14, dir, '0.14 0.08 0');
  311. };
  312.  
  313.  
  314. /*
  315. ==============================================================================
  316.  
  317. ROCKETS
  318.  
  319. ==============================================================================
  320. */
  321.  
  322. void()    s_explode1    =    [0,        s_explode2] {};
  323. void()    s_explode2    =    [1,        s_explode3] {};
  324. void()    s_explode3    =    [2,        s_explode4] {};
  325. void()    s_explode4    =    [3,        s_explode5] {};
  326. void()    s_explode5    =    [4,        s_explode6] {};
  327. void()    s_explode6    =    [5,        SUB_Remove] {};
  328.  
  329. void() BecomeExplosion =
  330. {
  331.     self.movetype = MOVETYPE_NONE;
  332.     self.velocity = '0 0 0';
  333.     self.touch = SUB_Null;
  334.     setmodel (self, "progs/s_explod.spr");
  335.     self.solid = SOLID_NOT;
  336.     s_explode1 ();
  337. };
  338.  
  339. void() T_MissileTouch =
  340. {
  341.     local float    damg;
  342.  
  343.     if (other == self.owner)
  344.         return;        // don't explode on owner
  345.  
  346.     if (pointcontents(self.origin) == CONTENT_SKY)
  347.     {
  348.         remove(self);
  349.         return;
  350.     }
  351.  
  352.     damg = 100 + random()*20;
  353.     
  354.     if (other.health)
  355.     {
  356.         if (other.classname == "monster_shambler")
  357.             damg = damg * 0.5;    // mostly immune
  358.         T_Damage (other, self, self.owner, damg );
  359.     }
  360.  
  361.     // don't do radius damage to the other, because all the damage
  362.     // was done in the impact
  363.     T_RadiusDamage (self, self.owner, 120, other);
  364.  
  365. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  366.     self.origin = self.origin - 8*normalize(self.velocity);
  367.  
  368.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  369.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  370.     WriteCoord (MSG_BROADCAST, self.origin_x);
  371.     WriteCoord (MSG_BROADCAST, self.origin_y);
  372.     WriteCoord (MSG_BROADCAST, self.origin_z);
  373.  
  374.     BecomeExplosion ();
  375. };
  376.  
  377.  
  378.  
  379. /*
  380. ================
  381. W_FireRocket
  382. ================
  383. */
  384. void() W_FireRocket =
  385. {
  386.     local    entity missile, mpuff;
  387.     
  388.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  389.     
  390.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  391.  
  392.     self.punchangle_x = -2;
  393.  
  394.     missile = spawn ();
  395.     missile.owner = self;
  396.     missile.movetype = MOVETYPE_FLYMISSILE;
  397.     missile.solid = SOLID_BBOX;
  398.         
  399. // set missile speed    
  400.  
  401.     makevectors (self.v_angle);
  402.     missile.velocity = aim(self, 1000);
  403.     missile.velocity = missile.velocity * 1000;
  404.     missile.angles = vectoangles(missile.velocity);
  405.     
  406.     missile.touch = T_MissileTouch;
  407.  
  408. // set missile duration
  409.     missile.nextthink = time + 5;
  410.     missile.think = SUB_Remove;
  411.  
  412.     setmodel (missile, "progs/missile.mdl");
  413.     setsize (missile, '0 0 0', '0 0 0');        
  414.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  415. };
  416.  
  417. /*
  418. ===============================================================================
  419.  
  420. LIGHTNING
  421.  
  422. ===============================================================================
  423. */
  424.  
  425. /*
  426. =================
  427. LightningDamage
  428. =================
  429. */
  430. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  431. {
  432.     local entity        e1, e2;
  433.     local vector        f;
  434.     
  435.     f = p2 - p1;
  436.     normalize (f);
  437.     f_x = 0 - f_y;
  438.     f_y = f_x;
  439.     f_z = 0;
  440.     f = f*16;
  441.  
  442.     e1 = e2 = world;
  443.  
  444.     traceline (p1, p2, FALSE, self);
  445.     if (trace_ent.takedamage)
  446.     {
  447.         particle (trace_endpos, '0 0 100', 225, damage*4);
  448.         T_Damage (trace_ent, from, from, damage);
  449.         if (self.classname == "player")
  450.         {
  451.             if (other.classname == "player")
  452.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  453.         }
  454.     }
  455.     e1 = trace_ent;
  456.  
  457.     traceline (p1 + f, p2 + f, FALSE, self);
  458.     if (trace_ent != e1 && trace_ent.takedamage)
  459.     {
  460.         particle (trace_endpos, '0 0 100', 225, damage*4);
  461.         T_Damage (trace_ent, from, from, damage);
  462.     }
  463.     e2 = trace_ent;
  464.  
  465.     traceline (p1 - f, p2 - f, FALSE, self);
  466.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage)
  467.     {
  468.         particle (trace_endpos, '0 0 100', 225, damage*4);
  469.         T_Damage (trace_ent, from, from, damage);
  470.     }
  471. };
  472.  
  473.  
  474. void() W_FireLightning =
  475. {
  476.     local    vector        org;
  477.  
  478.     if (self.ammo_cells < 1)
  479.     {
  480.         self.weapon = W_BestWeapon ();
  481.         W_SetCurrentAmmo ();
  482.         return;
  483.     }
  484.  
  485. // explode if under water
  486.     if (self.waterlevel > 1)
  487.     {
  488.         T_RadiusDamage (self, self, 35*self.ammo_cells, world);
  489.         self.ammo_cells = 0;
  490.         W_SetCurrentAmmo ();
  491.         return;
  492.     }
  493.  
  494.     if (self.t_width < time)
  495.     {
  496.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  497.         self.t_width = time + 0.6;
  498.     }
  499.     self.punchangle_x = -2;
  500.  
  501.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  502.  
  503.     org = self.origin + '0 0 16';
  504.     
  505.     traceline (org, org + v_forward*600, TRUE, self);
  506.  
  507.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  508.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  509.     WriteEntity (MSG_BROADCAST, self);
  510.     WriteCoord (MSG_BROADCAST, org_x);
  511.     WriteCoord (MSG_BROADCAST, org_y);
  512.     WriteCoord (MSG_BROADCAST, org_z);
  513.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  514.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  515.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  516.  
  517.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  518. };
  519.  
  520.  
  521. //=============================================================================
  522.  
  523.  
  524. void() GrenadeExplode =
  525. {
  526.     T_RadiusDamage (self, self.owner, 120, world);
  527.  
  528.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  529.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  530.     WriteCoord (MSG_BROADCAST, self.origin_x);
  531.     WriteCoord (MSG_BROADCAST, self.origin_y);
  532.     WriteCoord (MSG_BROADCAST, self.origin_z);
  533.  
  534.     BecomeExplosion ();
  535. };
  536.  
  537. void() GrenadeTouch =
  538. {
  539.     if (other == self.owner)
  540.         return;        // don't explode on owner
  541.     if (other.takedamage == DAMAGE_AIM)
  542.     {
  543.         GrenadeExplode();
  544.         return;
  545.     }
  546.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  547.     if (self.velocity == '0 0 0')
  548.         self.avelocity = '0 0 0';
  549. };
  550.  
  551. /*
  552. ================
  553. W_FireGrenade
  554. ================
  555. */
  556. void() W_FireGrenade =
  557. {
  558.     local    entity missile, mpuff;
  559.     
  560.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  561.     
  562.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  563.  
  564.     self.punchangle_x = -2;
  565.  
  566.     missile = spawn ();
  567.     missile.owner = self;
  568.     missile.movetype = MOVETYPE_BOUNCE;
  569.     missile.solid = SOLID_BBOX;
  570.     missile.classname = "grenade";
  571.         
  572. // set missile speed    
  573.  
  574.     makevectors (self.v_angle);
  575.  
  576.     if (self.v_angle_x)
  577.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  578.     else
  579.     {
  580.         missile.velocity = aim(self, 10000);
  581.         missile.velocity = missile.velocity * 600;
  582.         missile.velocity_z = 200;
  583.     }
  584.  
  585.     missile.avelocity = '300 300 300';
  586.  
  587.     missile.angles = vectoangles(missile.velocity);
  588.     
  589.     missile.touch = GrenadeTouch;
  590.     
  591. // set missile duration
  592.     missile.nextthink = time + 2.5;
  593.     missile.think = GrenadeExplode;
  594.  
  595.     setmodel (missile, "progs/grenade.mdl");
  596.     setsize (missile, '0 0 0', '0 0 0');        
  597.     setorigin (missile, self.origin);
  598. };
  599.  
  600. /*
  601. ===============
  602. Sticky Pipe Bombs
  603.  
  604. Used for player
  605. ===============
  606. */
  607.  
  608. void() BombExplode =
  609. {
  610.     T_RadiusDamage (self, self.owner, 128, world);
  611.  
  612.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  613.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  614.     WriteCoord (MSG_BROADCAST, self.origin_x);
  615.     WriteCoord (MSG_BROADCAST, self.origin_y);
  616.     WriteCoord (MSG_BROADCAST, self.origin_z);
  617.  
  618.     BecomeExplosion ();
  619. };
  620.  
  621. void() Detonate =
  622. {
  623.     local entity head;
  624.  
  625.     head = findradius (self.origin, 1500);
  626.     while(head)
  627.     {
  628.         if((head.classname == "bomb") && (head.owner == self))
  629.             head.nextthink = time;
  630.     head = head.chain;
  631.   }
  632. };
  633.  
  634. void() BombTouch =
  635. {
  636.     if (pointcontents(self.origin) == CONTENT_SKY)
  637.     {
  638.         remove(self);
  639.         return;
  640.     }
  641.   makevectors(self.origin);
  642.     self.velocity = self.velocity * 0;
  643.     self.avelocity = '0 0 0';
  644.     if (other.solid == SOLID_SLIDEBOX)
  645.         {
  646.             setorigin(self,other.origin);
  647.             if (temp1 == 3)
  648.                {
  649.           spawn_touchblood(24);
  650.                   sound(self,CHAN_WEAPON,"weapons/tink1.wav",1,ATTN_NORM);
  651.           temp1 = 1;
  652.                 }
  653.             else
  654.              {
  655.                  temp1 = temp1 + 1;
  656.        }
  657.                 
  658.     }
  659.     else
  660.         {
  661.           sound(self, CHAN_WEAPON, "player/axhit2.wav",1,ATTN_NORM);
  662.             setorigin(self,self.origin - (v_forward*10));
  663.             self.movetype = MOVETYPE_NONE;
  664.       self.touch = SUB_Null;
  665.         }
  666.  
  667. };
  668.  
  669. void() FireBomb =
  670. {
  671.     local entity bomb;
  672.  
  673.   if (self.ammo_rockets < 5)
  674.         return;
  675.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 5;
  676.     sound(self,CHAN_WEAPON,"weapons/grenade.wav",1,ATTN_NORM);
  677.     self.punchangle_x = -4;
  678.     //temp1 = 1;
  679.     bomb = spawn();
  680.     bomb.owner = self;
  681.     bomb.movetype = MOVETYPE_TOSS;
  682.     bomb.solid = SOLID_BBOX;
  683.     bomb.classname = "bomb";
  684.  
  685.     makevectors (self.v_angle);
  686.     bomb.velocity = aim(self, 1700);
  687.     bomb.velocity = bomb.velocity + v_forward*1700 + v_up * 200;
  688.     bomb.angles = vectoangles(bomb.velocity);                  
  689.     
  690.     bomb.touch = BombTouch;
  691.  
  692.     bomb.avelocity = '300 300 300';
  693.     bomb.think = BombExplode;
  694.  
  695.     setmodel (bomb, "progs/v_spike.mdl");
  696.     setsize (bomb, VEC_ORIGIN, VEC_ORIGIN);
  697.     setorigin (bomb,self.origin + '0 0 16' + (v_forward*25));
  698. };
  699.  
  700. void() spike_touch;
  701. void() superspike_touch;
  702.  
  703.  
  704. /*
  705. ===============
  706. launch_spike
  707.  
  708. Used for both the player and the ogre
  709. ===============
  710. */
  711. void(vector org, vector dir) launch_spike =
  712. {
  713.     newmis = spawn ();
  714.     newmis.owner = self;
  715.     newmis.movetype = MOVETYPE_FLYMISSILE;
  716.     newmis.solid = SOLID_BBOX;
  717.  
  718.     newmis.angles = vectoangles(dir);
  719.     
  720.     newmis.touch = spike_touch;
  721.     newmis.classname = "spike";
  722.     newmis.think = SUB_Remove;
  723.     newmis.nextthink = time + 6;
  724.     setmodel (newmis, "progs/spike.mdl");
  725.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  726.     setorigin (newmis, org);
  727.  
  728.     newmis.velocity = dir * 1000;
  729. };
  730.  
  731. void() W_FireSuperSpikes =
  732. {
  733.     local vector    dir;
  734.     local entity    old;
  735.     
  736.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  737.     self.attack_finished = time + 0.2;
  738.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  739.     dir = aim (self, 1000);
  740.     launch_spike (self.origin + '0 0 16', dir);
  741.     newmis.touch = superspike_touch;
  742.     setmodel (newmis, "progs/s_spike.mdl");
  743.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  744.     self.punchangle_x = -2;
  745. };
  746.  
  747. void(float ox) W_FireSpikes =
  748. {
  749.     local vector    dir;
  750.     local entity    old;
  751.     
  752.     makevectors (self.v_angle);
  753.     
  754.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  755.     {
  756.         W_FireSuperSpikes ();
  757.         return;
  758.     }
  759.  
  760.     if (self.ammo_nails < 1)
  761.     {
  762.         self.weapon = W_BestWeapon ();
  763.         W_SetCurrentAmmo ();
  764.         return;
  765.     }
  766.  
  767.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  768.     self.attack_finished = time + 0.2;
  769.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  770.     dir = aim (self, 1000);
  771.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  772.  
  773.     self.punchangle_x = -2;
  774. };
  775.  
  776.  
  777.  
  778. .float hit_z;
  779. void() spike_touch =
  780. {
  781. local float rand;
  782.     if (other == self.owner)
  783.         return;
  784.  
  785.     if (other.solid == SOLID_TRIGGER)
  786.         return;    // trigger field, do nothing
  787.  
  788.     if (pointcontents(self.origin) == CONTENT_SKY)
  789.     {
  790.         remove(self);
  791.         return;
  792.     }
  793.     
  794. // hit something that bleeds
  795.     if (other.takedamage)
  796.     {
  797.         spawn_touchblood (9);
  798.         T_Damage (other, self, self.owner, 9);
  799.     }
  800.     else
  801.     {
  802.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  803.         
  804.         if (self.classname == "wizspike")
  805.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  806.         else if (self.classname == "knightspike")
  807.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  808.         else
  809.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  810.         WriteCoord (MSG_BROADCAST, self.origin_x);
  811.         WriteCoord (MSG_BROADCAST, self.origin_y);
  812.         WriteCoord (MSG_BROADCAST, self.origin_z);
  813.     }
  814.  
  815.     remove(self);
  816.  
  817. };
  818.  
  819. void() superspike_touch =
  820. {
  821. local float rand;
  822.     if (other == self.owner)
  823.         return;
  824.  
  825.     if (other.solid == SOLID_TRIGGER)
  826.         return;    // trigger field, do nothing
  827.  
  828.     if (pointcontents(self.origin) == CONTENT_SKY)
  829.     {
  830.         remove(self);
  831.         return;
  832.     }
  833.     
  834. // hit something that bleeds
  835.     if (other.takedamage)
  836.     {
  837.         spawn_touchblood (18);
  838.         T_Damage (other, self, self.owner, 18);
  839.     }
  840.     else
  841.     {
  842.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  843.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  844.         WriteCoord (MSG_BROADCAST, self.origin_x);
  845.         WriteCoord (MSG_BROADCAST, self.origin_y);
  846.         WriteCoord (MSG_BROADCAST, self.origin_z);
  847.     }
  848.  
  849.     remove(self);
  850.  
  851. };
  852.  
  853.  
  854. /*
  855. ===============================================================================
  856.  
  857. PLAYER WEAPON USE
  858.  
  859. ===============================================================================
  860. */
  861.  
  862. void() W_SetCurrentAmmo =
  863. {
  864.     player_run ();        // get out of any weapon firing states
  865.  
  866.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  867.     
  868.     if (self.weapon == IT_AXE)
  869.     {
  870.         self.currentammo = 0;
  871.         self.weaponmodel = "progs/v_axe.mdl";
  872.         self.weaponframe = 0;
  873.     }
  874.     else if (self.weapon == IT_SHOTGUN)
  875.     {
  876.         self.currentammo = self.ammo_shells;
  877.         self.weaponmodel = "progs/v_shot.mdl";
  878.         self.weaponframe = 0;
  879.         self.items = self.items | IT_SHELLS;
  880.     }
  881.     else if (self.weapon == IT_SUPER_SHOTGUN)
  882.     {
  883.         self.currentammo = self.ammo_shells;
  884.         self.weaponmodel = "progs/v_shot2.mdl";
  885.         self.weaponframe = 0;
  886.         self.items = self.items | IT_SHELLS;
  887.     }
  888.     else if (self.weapon == IT_NAILGUN)
  889.     {
  890.         self.currentammo = self.ammo_nails;
  891.         self.weaponmodel = "progs/v_nail.mdl";
  892.         self.weaponframe = 0;
  893.         self.items = self.items | IT_NAILS;
  894.     }
  895.     else if (self.weapon == IT_SUPER_NAILGUN)
  896.     {
  897.         self.currentammo = self.ammo_nails;
  898.         self.weaponmodel = "progs/v_nail2.mdl";
  899.         self.weaponframe = 0;
  900.         self.items = self.items | IT_NAILS;
  901.     }
  902.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  903.     {
  904.         self.currentammo = self.ammo_rockets;
  905.         self.weaponmodel = "progs/v_rock.mdl";
  906.         self.weaponframe = 0;
  907.         self.items = self.items | IT_ROCKETS;
  908.     }
  909.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  910.     {
  911.         self.currentammo = self.ammo_rockets;
  912.         self.weaponmodel = "progs/v_rock2.mdl";
  913.         self.weaponframe = 0;
  914.         self.items = self.items | IT_ROCKETS;
  915.     }
  916.     else if (self.weapon == IT_LIGHTNING)
  917.     {
  918.         self.currentammo = self.ammo_cells;
  919.         self.weaponmodel = "progs/v_light.mdl";
  920.         self.weaponframe = 0;
  921.         self.items = self.items | IT_CELLS;
  922.     }
  923.     else if (self.weapon == IT_EXTRA_WEAPON)
  924.     {
  925.         self.currentammo = self.ammo_rockets;
  926.         self.weaponmodel = "progs/v_rock.mdl";
  927.         self.weaponframe = 0;
  928.     self.items = self.items | IT_ROCKETS;
  929.   }
  930.     else
  931.     {
  932.         self.currentammo = 0;
  933.         self.weaponmodel = "";
  934.         self.weaponframe = 0;
  935.     }
  936. };
  937.  
  938. float() W_BestWeapon =
  939. {
  940.     local    float    it;
  941.     
  942.     it = self.items;
  943.  
  944.     if(self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  945.         return IT_LIGHTNING;
  946.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  947.         return IT_SUPER_NAILGUN;
  948.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  949.         return IT_SUPER_SHOTGUN;
  950.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  951.         return IT_NAILGUN;
  952.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  953.         return IT_SHOTGUN;
  954.         
  955. /*
  956.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  957.         return IT_ROCKET_LAUNCHER;
  958.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  959.         return IT_GRENADE_LAUNCHER;
  960.  
  961. */
  962.  
  963.     return IT_AXE;
  964. };
  965.  
  966. float() W_CheckNoAmmo =
  967. {
  968.     if (self.currentammo > 0)
  969.         return TRUE;
  970.  
  971.     if (self.weapon == IT_AXE)
  972.         return TRUE;
  973.  
  974.     if ((self.weapon == IT_EXTRA_WEAPON) && (self.currentammo > 4))
  975.         return TRUE;
  976.     
  977.     self.weapon = W_BestWeapon ();
  978.  
  979.     W_SetCurrentAmmo ();
  980.     
  981. // drop the weapon down
  982.     return FALSE;
  983. };
  984.  
  985. /*
  986. ============
  987. W_Attack
  988.  
  989. An attack impulse can be triggered now
  990. ============
  991. */
  992. void()    player_axe1;
  993. void()    player_axeb1;
  994. void()    player_axec1;
  995. void()    player_axed1;
  996. void()    player_shot1;
  997. void()    player_nail1;
  998. void()    player_light1;
  999. void()    player_rocket1;
  1000.  
  1001. void() W_Attack =
  1002. {
  1003.     local    float    r;
  1004.  
  1005.     if (!W_CheckNoAmmo ())
  1006.         return;
  1007.  
  1008.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  1009.     self.show_hostile = time + 1;    // wake monsters up
  1010.  
  1011.     if (self.weapon == IT_AXE)
  1012.     {
  1013.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1014.         r = random();
  1015.         if (r < 0.25)
  1016.             player_axe1 ();
  1017.         else if (r<0.5)
  1018.             player_axeb1 ();
  1019.         else if (r<0.75)
  1020.             player_axec1 ();
  1021.         else
  1022.             player_axed1 ();
  1023.         self.attack_finished = time + 0.5;
  1024.     }
  1025.     else if (self.weapon == IT_SHOTGUN)
  1026.     {
  1027.         player_shot1 ();
  1028.         W_FireShotgun ();
  1029.         self.attack_finished = time + 0.5;
  1030.     }
  1031.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1032.     {
  1033.         player_shot1 ();
  1034.         W_FireSuperShotgun ();
  1035.         self.attack_finished = time + 0.7;
  1036.     }
  1037.     else if (self.weapon == IT_NAILGUN)
  1038.     {
  1039.         player_nail1 ();
  1040.     }
  1041.     else if (self.weapon == IT_SUPER_NAILGUN)
  1042.     {
  1043.         player_nail1 ();
  1044.     }
  1045.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1046.     {
  1047.         player_rocket1();
  1048.         W_FireGrenade();
  1049.         self.attack_finished = time + 0.6;
  1050.     }
  1051.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1052.     {
  1053.         player_rocket1();
  1054.         W_FireRocket();
  1055.         self.attack_finished = time + 0.8;
  1056.     }
  1057.     else if (self.weapon == IT_LIGHTNING)
  1058.     {
  1059.         player_light1();
  1060.         self.attack_finished = time + 0.1;
  1061.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1062.     }
  1063.     else if (self.weapon == IT_EXTRA_WEAPON)
  1064.     {
  1065.         player_rocket1();
  1066.         FireBomb();
  1067.     self.attack_finished = time + 0.6;
  1068.   }
  1069. };
  1070.  
  1071. /*
  1072. ============
  1073. W_ChangeWeapon
  1074.  
  1075. ============
  1076. */
  1077. void() W_ChangeWeapon =
  1078. {
  1079.     local    float    it, am, fl;
  1080.     
  1081.     it = self.items;
  1082.     am = 0;
  1083.     
  1084.     if (self.impulse == 1)
  1085.     {
  1086.         fl = IT_AXE;
  1087.     }
  1088.     else if (self.impulse == 2)
  1089.     {
  1090.         fl = IT_SHOTGUN;
  1091.         if (self.ammo_shells < 1)
  1092.             am = 1;
  1093.     }
  1094.     else if (self.impulse == 3)
  1095.     {
  1096.         fl = IT_SUPER_SHOTGUN;
  1097.         if (self.ammo_shells < 2)
  1098.             am = 1;
  1099.     }        
  1100.     else if (self.impulse == 4)
  1101.     {
  1102.         fl = IT_NAILGUN;
  1103.         if (self.ammo_nails < 1)
  1104.             am = 1;
  1105.     }
  1106.     else if (self.impulse == 5)
  1107.     {
  1108.         fl = IT_SUPER_NAILGUN;
  1109.         if (self.ammo_nails < 2)
  1110.             am = 1;
  1111.     }
  1112.     else if (self.impulse == 6)
  1113.     {
  1114.     if (self.weapon == IT_GRENADE_LAUNCHER)
  1115.       {
  1116.                 fl = IT_EXTRA_WEAPON;
  1117.                 if (self.ammo_rockets < 5)
  1118.           am = 1;
  1119.                 sprint(self, "Sticky Pipe Bombs\n");
  1120.       }   
  1121.         else
  1122.         {
  1123.             fl = IT_GRENADE_LAUNCHER;
  1124.             if (self.ammo_rockets < 1)
  1125.         am = 1;
  1126.             sprint(self, "Grenade Launcher\n");
  1127.         }
  1128.      }
  1129.     else if (self.impulse == 7)
  1130.     {
  1131.         fl = IT_ROCKET_LAUNCHER;
  1132.         if (self.ammo_rockets < 1)
  1133.             am = 1;
  1134.     }
  1135.     else if (self.impulse == 8)
  1136.     {
  1137.         fl = IT_LIGHTNING;
  1138.         if (self.ammo_cells < 1)
  1139.             am = 1;
  1140.     }
  1141.  
  1142.     self.impulse = 0;
  1143.     
  1144.     if (!(self.items & fl))
  1145.     {    // don't have the weapon or the ammo
  1146.         sprint (self, "no weapon.\n");
  1147.         return;
  1148.     }
  1149.     
  1150.     if (am)
  1151.     {    // don't have the ammo
  1152.         sprint (self, "not enough ammo.\n");
  1153.         return;
  1154.     }
  1155.  
  1156. //
  1157. // set weapon, set ammo
  1158. //
  1159.     self.weapon = fl;        
  1160.     W_SetCurrentAmmo ();
  1161. };
  1162.  
  1163. /*
  1164. ============
  1165. CheatCommand
  1166. ============
  1167. */
  1168. void() CheatCommand =
  1169. {
  1170.     if (deathmatch || coop)
  1171.         return;
  1172.  
  1173.     self.ammo_rockets = 100;
  1174.     self.ammo_nails = 200;
  1175.     self.ammo_shells = 100;
  1176.     self.items = self.items | 
  1177.         IT_AXE |
  1178.         IT_SHOTGUN |
  1179.         IT_SUPER_SHOTGUN |
  1180.         IT_NAILGUN |
  1181.         IT_SUPER_NAILGUN |
  1182.         IT_GRENADE_LAUNCHER |
  1183.         IT_ROCKET_LAUNCHER |
  1184.         IT_EXTRA_WEAPON |
  1185.         IT_KEY1 | IT_KEY2;
  1186.  
  1187.     self.ammo_cells = 200;
  1188.     self.items = self.items | IT_LIGHTNING;
  1189.  
  1190.     self.weapon = IT_ROCKET_LAUNCHER;
  1191.     self.impulse = 0;
  1192.     W_SetCurrentAmmo ();
  1193. };
  1194.  
  1195. /*
  1196. ============
  1197. CycleWeaponCommand
  1198.  
  1199. Go to the next weapon with ammo
  1200. ============
  1201. */
  1202. void() CycleWeaponCommand =
  1203. {
  1204.     local    float    it, am;
  1205.     
  1206.     it = self.items;
  1207.     self.impulse = 0;
  1208.     
  1209.     while (1)
  1210.     {
  1211.         am = 0;
  1212.  
  1213.         if (self.weapon == IT_LIGHTNING)
  1214.         {
  1215.             self.weapon = IT_AXE;
  1216.         }
  1217.         else if (self.weapon == IT_AXE)
  1218.         {
  1219.             self.weapon = IT_SHOTGUN;
  1220.             if (self.ammo_shells < 1)
  1221.                 am = 1;
  1222.         }
  1223.         else if (self.weapon == IT_SHOTGUN)
  1224.         {
  1225.             self.weapon = IT_SUPER_SHOTGUN;
  1226.             if (self.ammo_shells < 2)
  1227.                 am = 1;
  1228.         }        
  1229.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1230.         {
  1231.             self.weapon = IT_NAILGUN;
  1232.             if (self.ammo_nails < 1)
  1233.                 am = 1;
  1234.         }
  1235.         else if (self.weapon == IT_NAILGUN)
  1236.         {
  1237.             self.weapon = IT_SUPER_NAILGUN;
  1238.             if (self.ammo_nails < 2)
  1239.                 am = 1;
  1240.         }
  1241.         else if (self.weapon == IT_SUPER_NAILGUN)
  1242.         {
  1243.             self.weapon = IT_GRENADE_LAUNCHER;
  1244.             if (self.ammo_rockets < 1)
  1245.                 am = 1;
  1246.         }
  1247.         else if (self.weapon == IT_GRENADE_LAUNCHER)
  1248.         {
  1249.             self.weapon = IT_ROCKET_LAUNCHER;
  1250.             if (self.ammo_rockets < 1)
  1251.                 am = 1;
  1252.         }
  1253.         else if (self.weapon == IT_ROCKET_LAUNCHER)
  1254.         {
  1255.             self.weapon = IT_LIGHTNING;
  1256.             if (self.ammo_cells < 1)
  1257.                 am = 1;
  1258.         }
  1259.     
  1260.         if ( (self.items & self.weapon) && am == 0)
  1261.         {
  1262.             W_SetCurrentAmmo ();
  1263.             return;
  1264.         }
  1265.     }
  1266.  
  1267. };
  1268.  
  1269. /*
  1270. ============
  1271. ServerflagsCommand
  1272.  
  1273. Just for development
  1274. ============
  1275. */
  1276. void() ServerflagsCommand =
  1277. {
  1278.     serverflags = serverflags * 2 + 1;
  1279. };
  1280.  
  1281. void() QuadCheat =
  1282. {
  1283.     if (deathmatch || coop)
  1284.         return;
  1285.     self.super_time = 1;
  1286.     self.super_damage_finished = time + 30;
  1287.     self.items = self.items | IT_QUAD;
  1288.     dprint ("quad cheat\n");
  1289. };
  1290.  
  1291. /*
  1292. ============
  1293. ImpulseCommands
  1294.  
  1295. ============
  1296. */
  1297. void() ImpulseCommands =
  1298. {
  1299.     if (self.impulse >= 1 && self.impulse <= 8)
  1300.         W_ChangeWeapon ();
  1301.  
  1302.     if (self.impulse == 31)
  1303.         Detonate();
  1304.  
  1305.     if (self.impulse == 9)
  1306.         CheatCommand ();
  1307.     if (self.impulse == 10)
  1308.         CycleWeaponCommand ();
  1309.     if (self.impulse == 11)
  1310.         ServerflagsCommand ();
  1311.  
  1312.     if (self.impulse == 255)
  1313.         QuadCheat ();
  1314.         
  1315.     self.impulse = 0;
  1316. };
  1317.  
  1318. /*
  1319. ============
  1320. W_WeaponFrame
  1321.  
  1322. Called every frame so impulse events can be handled as well as possible
  1323. ============
  1324. */
  1325. void() W_WeaponFrame =
  1326. {
  1327.     if (time < self.attack_finished)
  1328.         return;
  1329.  
  1330.     ImpulseCommands ();
  1331.     
  1332. // check for attack
  1333.     if (self.button0)
  1334.     {
  1335.         SuperDamageSound ();
  1336.         W_Attack ();
  1337.     }
  1338. };
  1339.  
  1340. /*
  1341. ========
  1342. SuperDamageSound
  1343.  
  1344. Plays sound if needed
  1345. ========
  1346. */
  1347. void() SuperDamageSound =
  1348. {
  1349.     if (self.super_damage_finished > time)
  1350.     {
  1351.         if (self.super_sound < time)
  1352.         {
  1353.             self.super_sound = time + 1;
  1354.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  1355.         }
  1356.     }
  1357.     return;
  1358. };
  1359.  
  1360.  
  1361.